package com.mjk.common.tools.springextend;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.SmartApplicationListener;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
/**
 * 基于spring事件通知的异步执行器
 * 1 用于优化系统启动完成通知事件执行任务  阻塞 主线程，该类目的是把通知事件中
 *   非必要在系统初始化完成的，用异步处理完成
 *   节省系统启动的时间
 * @author mjk
 *
 */
public interface BeeApplicationListener extends ApplicationContextAware,SmartApplicationListener{
	/**
	 * 异步执行线程池
	 */
	ExecutorService pool =Executors.newFixedThreadPool(10, new CustomizableThreadFactory("HandleProcessor"));
	
	AtomicBoolean init = new AtomicBoolean(false);
	
	@Override	
	default void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		pool.execute(() -> doApplicationContext(applicationContext));
	}
	/**
	 * 规避多次运行问题
	 */
	@Override
	default  void onApplicationEvent(ApplicationEvent event) {
		ContextRefreshedEvent refrenshEvent = (ContextRefreshedEvent)event;
		ApplicationContext parent = refrenshEvent.getApplicationContext().getParent();
		if (parent==null||parent.getParent() == null) {
			pool.execute(() -> doApplicationEvent(refrenshEvent));
		}
	}
	// 设置该监听器的执行顺序，数字越小越先执行
	@Override
	default  int getOrder() {
		return -1;
	}

	@Override
	default  boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
		return eventType == ContextRefreshedEvent.class;
	}

	@Override
	default  boolean supportsSourceType(Class<?> sourceType) {
		return true;
	}
	/**
	 * 执行setApplicationContext方法
	 */
	default void doApplicationContext(ApplicationContext applicationContext){}
	/**
	 * 时间通知执行	
	 */
	default void doApplicationEvent(ContextRefreshedEvent event){}
}
